use serde::{Deserialize, Serialize};
use std::collections::VecDeque;

#[derive(Serialize, Deserialize)]
#[serde(transparent)]
pub struct History<T> {
    timeline: VecDeque<T>,
    #[serde(skip, default = "default_max")]
    max: usize,
}

fn default_max() -> usize {
    usize::MAX
}

impl<T> History<T> {
    pub fn new() -> Self {
        Self {
            timeline: VecDeque::new(),
            max: default_max(),
        }
    }

    pub fn set_max(&mut self, max: usize) {
        self.max = max;
        self.timeline.truncate(self.max);
    }

    pub fn push(&mut self, value: T) {
        self.timeline.push_front(value);
        self.timeline.truncate(self.max);
    }

    pub fn pop(&mut self) -> Option<T> {
        self.timeline.pop_front()
    }
}

#[cfg(test)]
mod test {
    use super::History;
    use proptest::{prop_assert_eq, proptest};
    use serde_json::{from_str, to_string};

    proptest!(
        #[test]
        fn test(val: Vec<u8>) {
            let mut h = History::new();
            h.set_max(val.len());

            h.push(114);
            for &val in &val {
                h.push(val);
            }
            prop_assert_eq!(h.timeline.len(), val.len());

            prop_assert_eq!(
                &h.timeline,
                &from_str::<History<_>>(&to_string(&h).unwrap())
                    .unwrap()
                    .timeline
            );

            for &val in val.iter().rev() {
                prop_assert_eq!(h.pop(), Some(val));
            }
            prop_assert_eq!(h.pop(), None);
        }
    );
}
